package siruna.WE.core.BlockFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import siruna.WE.core.Constants.Visual;
import siruna.WE.core.events.EventListener;
import siruna.WE.core.model.Block;
import siruna.WE.core.model.Container;
import siruna.WE.core.model.EventList;
import siruna.WE.core.model.FunctionalBlock;
import siruna.WE.core.model.VisualBlock;
import siruna.WE.core.model.VisualBlocks.ButtonImpl;
import siruna.WE.core.model.VisualBlocks.ImageImpl;
import siruna.WE.core.model.VisualBlocks.LabelImpl;
import siruna.WE.core.model.container.ContentImpl;
import siruna.WE.core.model.container.PageImpl;

public class VisualBlockFactory {

	LinkedHashMap<String, VisualBlock> visBlocks;
	EventListener eventhandler;
	private ZipFile zipFile;
	private String widgetName;

	public VisualBlockFactory(EventListener eventhandler, ZipFile zipFile, String widgetName) {
		visBlocks = new LinkedHashMap<String, VisualBlock>();
		this.eventhandler = eventhandler;
		this.zipFile = zipFile;
		this.widgetName = widgetName;

	}

	public LinkedHashMap<String, VisualBlock> makeVisualBlocks(NodeList vis) {
		// TODO Auto-generated method stu
		for (int i = 0; i < vis.getLength(); i++) {
			Node n = vis.item(i);
			behandelNodeRec(n);
		}

		for (VisualBlock b : visBlocks.values()) {
			System.out.println("tt: " + b.getId());

		}

		return visBlocks;

	}

	private void behandelNodeRec(Node n) {

		createVisualBlock(n);

		System.out.println(n.getNodeName());

		NodeList list = n.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			if (list.item(i).getNodeType() == Document.ELEMENT_NODE) {
				behandelNodeRec(list.item(i));
			}
		}

	}

	private void createVisualBlock(Node n) {
		NamedNodeMap att = n.getAttributes();
		VisualBlock b = null;

		Class calc;

		try {
			calc = Class.forName("siruna.WE.core.model.VisualBlocks."
					+ n.getNodeName() + "Impl");

			b = (VisualBlock) calc.newInstance();

		} catch (ClassNotFoundException e2) {
			// het kan nog een container zijn
			try {
				System.out.println("Classnotfound in VisualBlocks: "+e2.getMessage());
				calc = Class.forName("siruna.WE.core.model.container."
						+ n.getNodeName() + "Impl");
				Container vc = (Container) calc.newInstance();
				addChildIds(n, vc);
				b = vc;

			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (b instanceof ImageImpl) {
			ImageImpl vi = (ImageImpl) b;

			if (att.getNamedItem("img").getNodeValue() != null) {
				ZipEntry e = zipFile.getEntry(att.getNamedItem("img")
						.getNodeValue());

				try {
					InputStream is = zipFile.getInputStream(e);
					System.out.println("is.available() " + is.available());
					byte[] theBytes = inputStreamToBytes(is);
					System.out.println("theBytes.length: " + theBytes.length);

					vi.setBytes(theBytes);

				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			b = vi;
		}

		if (b != null) {
			setIdAndAttributes(att, b);
			save(b);
			b.setEventHandler(eventhandler);
			b.setWidgetName(widgetName);
		}
	}

	private void save(VisualBlock b) {
		visBlocks.put(b.getId(), b);

	}

	private void setIdAndAttributes(NamedNodeMap att, VisualBlock vb) {
		vb.setId(att.getNamedItem("Id").getNodeValue());
		att.removeNamedItem("Id");
		for (int i = 0; i < att.getLength(); i++) {
			vb.setAttribute(att.item(i).getNodeName(), att.item(i)
					.getNodeValue());
		}
	}

	private void addChildIds(Node n, Container vc) {
		NodeList list = n.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			if (list.item(i).getNodeType() == Document.ELEMENT_NODE) {
				vc.addChildId(list.item(i).getAttributes().getNamedItem("Id")
						.getNodeValue());
			}
		}
	}

	private byte[] inputStreamToBytes(InputStream in) throws IOException {

		ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
		byte[] buffer = new byte[1024];
		int len;

		while ((len = in.read(buffer)) >= 0)
			out.write(buffer, 0, len);

		in.close();
		out.close();
		return out.toByteArray();
	}
}
